% 仿真qpsk调制的基带数字信号经过awgn信道
clear all;              %清空工作区变量
nSamp = 8;              %矩形脉冲的取样点数
numSymb = 200000;       %每种SNR下的传输的符号数
M=4;                    %QPSK的符号类型数
SNR=-30:2:3;            %SNR的范围
grayencod=[0 1 3 2];    %Gray编码格式

% 扩频码
mseq = [[-1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1];[-1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1]];  % 15位长m序列
codes = {mseq}; 
codes{end+1} = [[1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1]; [1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1]];  % 13位长巴克码

codes{end+1} = [[1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1]; [1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1]];  % 13位长巴克码偶（主峰为11）

codes{end+1} = [[1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1]; [1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1]];  % 15位长巴克码偶（主峰为11）

codes{end+1} = [[1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1]; [1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1]];  % 18位长巴克码偶（主峰为16）

codes{end+1} = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1]; [1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1]];  % 21位长巴克码偶（主峰为11）

codes_string = ["15位长m序列","13位长巴克码","13位长巴克码偶（主峰为11）","15位长巴克码偶（主峰为11）","18位长巴克码偶（主峰为16）","21位长巴克码偶（主峰为11）"];


for ii=1:length(SNR)  % 循环遍历每种SNR
    for code_idx = 1:length(codes)  % 循环遍历每种扩频码
        x = codes{code_idx}(1, :);  % 当前扩频码的x
        y = codes{code_idx}(2, :);  % 当前扩频码的y

        msg=randsrc(1,numSymb,0:3);             %产生发送符号，长度为numSymb，每个元素都是0到3之间的整数
        msg_gr=grayencod(msg+1);                %进行Gray编码映射，Gray编码是一种将符号映射到二进制码字的编码方式，相邻的符号对应的码字只有一位不同，可以有效降低误码率。
        msg_tx=pskmod(msg_gr,M);                %QPSK调制得到基带数字信号

        msg_tx_sp = zeros(1,length(msg_tx)*length(x)); %初始化扩频后的信号
        for j = 1:length(msg_tx)
            msg_tx_sp((j-1)*length(x)+1 : j*length(x)) = x.*msg_tx(j); %扩频
        end

        msg_tx_sp = rectpulse(msg_tx_sp, nSamp);    %矩形脉冲成形
        msg_rx=awgn(msg_tx_sp,SNR(ii),'measured');  %通过AWGN信道
        msg_rx_down = intdump(msg_rx,nSamp);        %匹配滤波相干解调    
        
        msg_rx_down_sp = zeros(1,length(msg_rx_down)/length(y));  %初始化解扩信号
        for j = 1:length(msg_rx_down_sp)
            msg_rx_down_sp(j) = sum(msg_rx_down((j-1)*length(y)+1 : j*length(y)).* y); %去扩频
        end
        msg_gr_demod = pskdemod(msg_rx_down_sp,M); %QPSK解调
        [dummy, graydecod] = sort(grayencod); 
        graydecod = graydecod - 1;
        msg_demod = graydecod(msg_gr_demod+1); % Gray编码逆映射
        [errorBit, BER(code_idx,ii)] = biterr(msg, msg_demod, log2(M)); %计算BER
        [errorSym, SER(code_idx,ii)] = symerr(msg, msg_demod);          %计算SER
    end
end


% 画出BER和SER随SNR变化的曲线
figure
semilogy(SNR,SER(1,:),'-+', ...
         SNR,SER(2,:),'-.', ...
         SNR,SER(3,:),'-*', ...
         SNR,SER(4,:),'-p', ...
         SNR,SER(5,:),'-v', ...
         SNR,SER(6,:),'-s')   
legend(codes_string)
title('QPSK在AWGN信道下的性能')
xlabel('信噪比（dB）')
ylabel('误符号率')

figure
semilogy(SNR,BER(1,:),'-+', ...
         SNR,BER(2,:),'-.', ...
         SNR,BER(3,:),'-*', ...
         SNR,BER(4,:),'-p', ...
         SNR,BER(5,:),'-v', ...
         SNR,BER(6,:),'-s')   
legend(codes_string)
title('QPSK在AWGN信道下的性能')
xlabel('信噪比（dB）')
ylabel('误比特率')